use futures_util::StreamExt;
use num_cpus;
use reqwest::{
    header::{HeaderMap, HeaderValue, RANGE},
    Client,
};
use std::sync::Arc;
use tokio::fs::{File, OpenOptions};
use tokio::io::{AsyncSeekExt, AsyncWriteExt};
use tauri::{AppHandle, Emitter};

use crate::download_manager::{DownloadTask, DownloadStatus, HttpSettings};

const CHUNK_SIZE: u64 = 1024 * 1024; // 1MB 每个分片
const MIN_MULTI_THREAD_SIZE: u64 = 2 * 1024 * 1024; // 最小多线程下载大小为 2MB

// async fn check_url_protocol(url: &str) -> Result<(), String> {
//     let url = url.to_lowercase();
//     if !url.starts_with("http://") && !url.starts_with("https://") {
//         return Err("仅支持HTTP和HTTPS协议".to_string());
//     }
//     Ok(())
// }

async fn follow_redirects(client: &Client, url: &str) -> Result<(String, bool), String> {
    let resp = client.get(url).send().await.map_err(|e| e.to_string())?;

    let final_url = resp.url().to_string();
    let is_redirected = final_url != url;

    Ok((final_url, is_redirected))
}

async fn check_range_support(url: &str, settings: &HttpSettings) -> Result<bool, String> {
    let mut client_builder = Client::builder();
    
    // 配置证书验证
    client_builder = client_builder.danger_accept_invalid_certs(!settings.check_certificate);
    
    // 配置代理
    if !settings.http_proxy.is_empty() {
        let proxy = reqwest::Proxy::http(&settings.http_proxy)
            .map_err(|e| e.to_string())?;
        if !settings.http_proxy_user.is_empty() {
            let proxy = proxy.clone(); // 克隆代理对象
            proxy.basic_auth(&settings.http_proxy_user, &settings.http_proxy_passwd);
        }
        client_builder = client_builder.proxy(proxy);
    }
    if !settings.https_proxy.is_empty() {
        let proxy = reqwest::Proxy::https(&settings.https_proxy)
            .map_err(|e| e.to_string())?;
        if !settings.https_proxy_user.is_empty() {
            let proxy = proxy.clone(); // 克隆代理对象
            proxy.basic_auth(&settings.https_proxy_user, &settings.https_proxy_passwd);
        }
        client_builder = client_builder.proxy(proxy);
    }
    
    // 创建客户端
    let client = client_builder.build().map_err(|e| e.to_string())?;
    
    // 构建请求
    let mut request = client.head(url);
    
    // 设置 User-Agent
    if !settings.user_agent.is_empty() {
        request = request.header("User-Agent", &settings.user_agent);
    }
    
    // 设置自定义请求头
    if !settings.custom_headers.is_empty() {
        for line in settings.custom_headers.lines() {
            if let Some((key, value)) = line.split_once(':') {
                request = request.header(key.trim(), value.trim());
            }
        }
    }
    
    let resp = request.send().await.map_err(|e| e.to_string())?;

    let supports_range = resp
        .headers()
        .get("accept-ranges")
        .and_then(|v| v.to_str().ok())
        .map_or(false, |v| v == "bytes");

    println!("服务器是否支持断点续传: {}", supports_range);
    Ok(supports_range)
}

// 根据 CPU 核心数确定最大线程数
fn get_max_threads() -> u32 {
    let cpu_count = num_cpus::get();
    if cpu_count <= 1 {
        1
    } else {
        (cpu_count - 1) as u32
    }
}

pub async fn download_with_threads(
    app_handle: AppHandle,
    task: Arc<DownloadTask>,
    supports_range: bool,
) -> Result<String, String> {
    let settings = crate::download_manager::DOWNLOAD_MANAGER.settings.read().await;
    let mut client_builder = Client::builder()
        .danger_accept_invalid_certs(!settings.check_certificate);

    // 如果不接受 gzip 压缩，则禁用它
    if !settings.http_accept_gzip {
        client_builder = client_builder.no_gzip();
    }

    // 配置代理
    if !settings.http_proxy.is_empty() {
        let proxy = reqwest::Proxy::http(&settings.http_proxy)
            .map_err(|e| e.to_string())?;
        if !settings.http_proxy_user.is_empty() {
            let proxy = proxy.clone(); // 克隆代理对象
            proxy.basic_auth(&settings.http_proxy_user, &settings.http_proxy_passwd);
        }
        client_builder = client_builder.proxy(proxy);
    }
    if !settings.https_proxy.is_empty() {
        let proxy = reqwest::Proxy::https(&settings.https_proxy)
            .map_err(|e| e.to_string())?;
        if !settings.https_proxy_user.is_empty() {
            let proxy = proxy.clone(); // 克隆代理对象
            proxy.basic_auth(&settings.https_proxy_user, &settings.https_proxy_passwd);
        }
        client_builder = client_builder.proxy(proxy);
    }

    let client = client_builder.build().map_err(|e| e.to_string())?;
    let mut request = client.get(&task.url);

    // 设置 User-Agent
    if !settings.user_agent.is_empty() {
        request = request.header("User-Agent", &settings.user_agent);
    }

    // 设置自定义请求头
    if !settings.custom_headers.is_empty() {
        for line in settings.custom_headers.lines() {
            if let Some((key, value)) = line.split_once(':') {
                request = request.header(key.trim(), value.trim());
            }
        }
    }

    let resp = request.send().await.map_err(|e| e.to_string())?;

    let total_size = resp.content_length().unwrap_or(0);

    {
        let mut progress = task.progress.write().await;
        progress.total_size = total_size;
        progress.status = DownloadStatus::Downloading;
    }

    let file = Arc::new(tokio::sync::Mutex::new(
        OpenOptions::new()
            .create(true)
            .write(true)
            .open(format!("{}/{}", task.path, task.file_name))
            .await
            .map_err(|e| e.to_string())?,
    ));

    // 如果文件太小或服务器不支持断点续传，使用单线程下载
    let actual_threads = if total_size < MIN_MULTI_THREAD_SIZE || !supports_range {
        1
    } else {
        std::cmp::min(get_max_threads(), (total_size / CHUNK_SIZE) as u32)
    };

    let chunk_size = total_size / actual_threads as u64;

    let mut handles = vec![];

    let mut thread_progress = Vec::new();
    for i in 0..actual_threads {
        let start = i as u64 * chunk_size;
        let end = if i == actual_threads - 1 {
            total_size - 1
        } else {
            (i as u64 + 1) * chunk_size - 1
        };

        thread_progress.push(crate::download_manager::ThreadProgress {
            thread_id: i,
            start_pos: start,
            end_pos: end,
            current_pos: start,
        });
    }

    // 初始化时就设置线程进度
    {
        let mut progress = task.progress.write().await;
        progress.thread_progress = thread_progress.clone(); // 克隆一份给进度对象

        // 发送初始进度信息
        let progress_clone = progress.clone();
        drop(progress);
        app_handle
            .emit("download_progress", progress_clone)
            .map_err(|e| e.to_string())?;
    }

    // 为每个线程创建下载任务
    for i in 0..actual_threads {
        let start = thread_progress[i as usize].start_pos;
        let end = thread_progress[i as usize].end_pos;

        let task = task.clone();
        let file = file.clone();
        let client = client.clone();
        let app_handle = app_handle.clone();

        handles.push(tokio::spawn(async move {
            download_chunk(
                &client,
                &task.url,
                start,
                end,
                file,
                task.clone(),
                app_handle,
            )
            .await
        }));
    }

    for handle in handles {
        handle.await.map_err(|e| e.to_string())??;
    }

    {
        let mut progress = task.progress.write().await;
        if progress.status != DownloadStatus::Paused {
            progress.status = DownloadStatus::Completed;
            progress.progress = 100.0;

            // 发送最终状态更新到前端
            let progress_clone = progress.clone();
            drop(progress);
            app_handle
                .emit("download_progress", progress_clone)
                .map_err(|e| e.to_string())?;
        }
    }

    Ok("下载完成".to_string())
}

async fn download_chunk(
    client: &Client,
    url: &str,
    start: u64,
    end: u64,
    file: Arc<tokio::sync::Mutex<File>>,
    task: Arc<DownloadTask>,
    app_handle: AppHandle,
) -> Result<(), String> {
    // 先检查任务是否已经暂停
    let progress = task.progress.read().await;
    if progress.status == DownloadStatus::Paused {
        return Ok(());
    }
    drop(progress);

    let mut headers = HeaderMap::new();
    headers.insert(
        RANGE,
        HeaderValue::from_str(&format!("bytes={}-{}", start, end)).unwrap(),
    );

    let resp = client
        .get(url)
        .headers(headers.clone())
        .send()
        .await
        .map_err(|e| e.to_string())?;

    // 处理动态生成的内容
    let content_length = resp.content_length();
    if content_length.is_none() {
        println!("检测到动态生成的内容，使用流式下载");
    }

    let mut stream = resp.bytes_stream();
    let mut current_pos = start;

    // 获取当前线程的进度信息
    let progress = task.progress.read().await;
    if let Some(thread_prog) = progress
        .thread_progress
        .iter()
        .find(|tp| tp.start_pos == start && tp.end_pos == end)
    {
        // 从上次下载的位置继续
        current_pos = thread_prog.current_pos;
        // 更新请求头中的范围
        headers.insert(
            RANGE,
            HeaderValue::from_str(&format!("bytes={}-{}", current_pos, end)).unwrap(),
        );
    }
    drop(progress);

    // 如果有未完成的部分，重新发起请求
    if current_pos > start {
        let resp = client
            .get(url)
            .headers(headers)
            .send()
            .await
            .map_err(|e| e.to_string())?;
        stream = resp.bytes_stream();
    }

    while let Some(chunk) = stream.next().await {
        if *task.cancel_flag.read().await {
            return Ok(());
        }

        let chunk = chunk.map_err(|e| e.to_string())?;
        let mut file = file.lock().await;
        file.seek(std::io::SeekFrom::Start(current_pos))
            .await
            .map_err(|e| e.to_string())?;
        file.write_all(&chunk).await.map_err(|e| e.to_string())?;

        current_pos += chunk.len() as u64;

        let mut progress = task.progress.write().await;

        // 更新对应线程的进度
        if let Some(thread_prog) = progress
            .thread_progress
            .iter_mut()
            .find(|tp| tp.start_pos == start && tp.end_pos == end)
        {
            thread_prog.current_pos = current_pos;
        }

        // 对于动态生成的内容，实时更新总大小
        if content_length.is_none() {
            progress.total_size = progress.downloaded_size;
        }

        progress.downloaded_size += chunk.len() as u64;
        progress.progress = (progress.downloaded_size as f64 / progress.total_size as f64) * 100.0;

        let progress_clone = progress.clone();
        drop(progress);

        app_handle
            .emit("download_progress", progress_clone)
            .map_err(|e| e.to_string())?;
    }

    Ok(())
}
